﻿using SqlSugar;
using SqlSugar.Extensions;
using System.Linq.Expressions;
using System.Reflection;
using System.Security.AccessControl;
using WareHouse.Domain;
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using IdentityModel;
using System.Drawing.Printing;
using System.Collections.Generic;

namespace WareHouse.Repositories
{
    public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : class, new()
    {
        private readonly ISqlSugarClient db;

        public BaseRepository(ISqlSugarClient db)
        {
            this.db = db;
        }

        public IHttpContextAccessor? httpContextAccessor { get; set; }
        /// <summary>
        /// 添加
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual async Task<long> InsertAsync(TEntity entity)
        {
            //反射
            Type type = entity.GetType();

            PropertyInfo[] propertyInfos = type.GetProperties();
            if (httpContextAccessor?.HttpContext.User.Identity?.IsAuthenticated==true)
            {
                var claims = httpContextAccessor?.HttpContext.User.Claims;

                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    if (propertyInfo.Name == nameof(AuditInfo.AddId))
                    {
                        var id = Convert.ToInt64(claims?.First(m=>m.Type== JwtClaimTypes.Id).Value);
                        propertyInfo.SetValue(entity, id);
                    }

                    if (propertyInfo.Name == nameof(AuditInfo.AddPerson))
                    {
                        var  name=claims?.First(m=>m.Type == JwtClaimTypes.Name).Value;
                        propertyInfo.SetValue(entity, name);
                    }
                    if (propertyInfo.Name == nameof(AuditInfo.AddDate))
                    {
                        propertyInfo.SetValue(entity, DateTime.Now);
                    }
                }
            }
            

            return await db.Insertable<TEntity>(entity).ExecuteReturnSnowflakeIdAsync();
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public virtual async Task<TEntity> UpdateAsync(TEntity entity)
        {
            await db.Updateable<TEntity>(entity)
            .IgnoreColumns(
            nameof(AuditInfo.AddId),
            nameof(AuditInfo.AddPerson),
            nameof(AuditInfo.AddDate),
            nameof(AuditInfo.IsDel),
            nameof(AuditInfo.DelId),
            nameof(AuditInfo.DelPerson),
            nameof(AuditInfo.DelDate)
            ).ExecuteCommandAsync();
            return entity;
        }


        /// <summary>
        /// 查询单条
        /// </summary>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public virtual async Task<TEntity> FistAsync(Expression<Func<TEntity, bool>> predicate)
        {
            var eneity = await db.Queryable<TEntity>().FirstAsync(predicate);
            return eneity;
        }
        /// <summary>
        /// 查全部
        /// </summary>
        /// <returns></returns>
        public virtual async Task<List<TEntity>> QueryAsync()
        {
            var list = await db.Queryable<TEntity>().ToListAsync();
            return list;
        }
        /// <summary>
        /// 按条件查询
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual async Task<List<TEntity>> QueryAsync(Expression<Func<TEntity, bool>> expression)
        {
            var list = await db.Queryable<TEntity>().Where(expression).ToListAsync();
            return list;
        }
        /// <summary>
        /// 分页
        /// </summary>
        /// <param name="PageIndex"></param>
        /// <param name="PageSize"></param>
        /// <param name="expression"></param>
        /// <returns></returns>
        public virtual async Task<(int,List<TEntity>)> PageAsync(int PageIndex,int PageSize,Expression<Func<TEntity,bool>> expression)
        {
            RefAsync<int> total = 0;//REF和OUT不支持异步,想要真的异步这是最优解
            var list = await db.Queryable<TEntity>().Where(expression).ToPageListAsync(PageIndex, PageSize, total);//ToPageAsync

            return (total, list);
        }

        /// <summary>
        /// 单个删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<int> Delete(long id)
        {
            Type type = typeof(TEntity);
            if (type.GetProperties().Any(x => x.Name == nameof(AuditInfo.IsDel)))
            {
                return await db.Deleteable<TEntity>().In(id).IsLogic().ExecuteCommandAsync(nameof(AuditInfo.IsDel), true, nameof(AuditInfo.DelDate), nameof(AuditInfo.DelPerson), httpContextAccessor?.HttpContext?.User.Identity?.Name);
            }
            else
            {
                return await db.Deleteable<TEntity>().ExecuteCommandAsync();
            }


        }
        //删除单条
        public virtual async Task<long> DeleAsync(long id)
        {
            return await db.Deleteable<TEntity>().In(id).ExecuteCommandAsync();
        }

        //批量删除  //没用到这个 你下面这个传单个string 怎么可能批量删除   你得穿 string数组 你不会直接传数组啊
        //好了现在  我调一下 你先忙 /你别退 //干啥  我写了

        public virtual async Task<long> DeleAsyncList1(string id)
        {
            string[] ids = id.Split(',');
            foreach (var item in ids)
            {
             
                await db.Deleteable<TEntity>().In(Convert.ToUInt32(item)).ExecuteCommandAsync();
            }
            return 1;

           //piliangzala? 对 这是仓储 然后呢  你看看对不对逻辑 你直接删除前段传过来的类就行了 不用穿id啊
            
        }



        public virtual List<TEntity> Queryable()
        {
            return db.Queryable<TEntity>().ToList();
        }




    }
}